// Builder.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdlib.h>
#include <string>

class Product
{
public:
	void Operation()
	{
		printf(m_strValue.c_str());
	}

	void Append(std::string part)
	{
		m_strValue.append(part);
	}
private:
	std::string m_strValue;
};

class Builder
{
public:
	Product* GetProduct(std::string param1, std::string param2)
	{
		m_Product = new Product;
		CreatePartA(param1, param2);
		CreatePartB(param1, param2);
		CreatePartC(param1, param2);
		return m_Product;
	}

protected:
	virtual void CreatePartA(std::string param1, std::string param2){};
	virtual void CreatePartB(std::string param1, std::string param2){};
	virtual void CreatePartC(std::string param1, std::string param2){};

	Product* m_Product;
};

class RealBuilderA : public Builder
{
public:
	virtual void CreatePartA(std::string param1, std::string param2)
	{	
		if (m_Product)
		{
			std::string str = "build part a:";
			str = str + param1 + param2 + "\n";
			m_Product->Append(str);
		}
	}
	virtual void CreatePartB(std::string param1, std::string param2)
	{
		if (m_Product)
		{
			std::string str = "build part B:";
			str = str + param1 + param2 + "\n";
			m_Product->Append(str);
		}
	}
	virtual void CreatePartC(std::string param1, std::string param2)
	{
		if (m_Product)
		{
			std::string str = "build part C:";
			str = str + param1 + param2 + "\n";
			m_Product->Append(str);
		}
	}
};

class RealBuilderB : public Builder
{
public:
	virtual void CreatePartA(std::string param1, std::string param2)
	{	
		if (m_Product)
		{
			std::string str = "build part a:";
			str = str + param2 + param1 + "\n";
			m_Product->Append(str);
		}
	}
	virtual void CreatePartB(std::string param1, std::string param2)
	{
		if (m_Product)
		{
			std::string str = "build part B:";
			str = str + param2 + param1 + "\n";
			m_Product->Append(str);
		}
	}
	virtual void CreatePartC(std::string param1, std::string param2)
	{
		if (m_Product)
		{
			std::string str = "build part C:";
			str = str + param2 + param1 + "\n";
			m_Product->Append(str);
		}
	}
};

class Constructor
{
public:
	void SetBuilder(Builder* pBuilder)
	{
		m_pBuilder = pBuilder;
	}

	Product* Construct(std::string param1, std::string param2)
	{
		if (m_pBuilder)
		{
			return m_pBuilder->GetProduct(param1, param2);
		}

		return NULL;
	}

private:
	Builder* m_pBuilder;
};

int _tmain(int argc, _TCHAR* argv[])
{
	Constructor Dirctor;
	Builder* pBuilder = new RealBuilderA;
	Dirctor.SetBuilder(pBuilder);
	Product* pProduct = Dirctor.Construct("aaaa", "bbbbb");
	pProduct->Operation();

	Builder* pBuilderB = new RealBuilderB;
	Dirctor.SetBuilder(pBuilderB);
	pProduct = Dirctor.Construct("aaaa", "bbbbb");
	pProduct->Operation();

	system("pause");
	return 0;
}

